package cn.com.generaldata.os.service.indicator_evaluation.industry_structure_analysis;

import org.apache.commons.lang3.Validate;
import org.nutz.dao.sql.Criteria;

import cn.com.generaldata.jsme_indicator_system.entity.IndicatorEvaluation;
import cn.com.generaldata.os.service.indicator_constant.ProvinceIndicatorConstant;
import cn.com.generaldata.os.service.indicator_evaluation.IndicatorEvaluationCalculateService;
import cn.com.generaldata.os.vo.IndicatorAccountVO;

/**
 * Moore结构变化同比评估指标计算类.
 */
public class MooreStructureLastChangeCalculateService extends IndicatorEvaluationCalculateService {

	private String BaseIndicatorName = ProvinceIndicatorConstant.GOP_INDICATOR_NAME;
	private String FirstIndicatorName = ProvinceIndicatorConstant.FIRST_RATE_INDICATOR_NAME;
	private String SecondIndicatorName = ProvinceIndicatorConstant.SECOND_RATE_INDICATOR_NAME;
	private String ThirdIndicatorName = ProvinceIndicatorConstant.THIRD_RATE_INDICATOR_NAME;
	private String FirstName = ProvinceIndicatorConstant.FIRST_INDICATOR_NAME;
	private String SecondName = ProvinceIndicatorConstant.SECOND_INDICATOR_NAME;
	private String ThirdName = ProvinceIndicatorConstant.THIRD_INDICATOR_NAME;

	@Override
	protected Double calculate(IndicatorEvaluation indicator, IndicatorAccountVO indicatorAccountVO) {
		// 同比年份
		int fixBaseYear = indicatorAccountVO.getYear() - 1;
		Double currentBase = getBaseIndicatorVal(indicatorAccountVO, fixBaseYear);
		Double firstBase = geFirstIndicatorVal(indicatorAccountVO, fixBaseYear, FirstName);
		Double secontBase = geFirstIndicatorVal(indicatorAccountVO, fixBaseYear, SecondName);
		Double thirdBase = geFirstIndicatorVal(indicatorAccountVO, fixBaseYear, ThirdName);

		Validate.isTrue(!(Double.valueOf(0).equals(currentBase)));
		// 同比第一产业比重
		Double firstBasetoGOP = currentBase == 0 ? 0 : (firstBase / currentBase) * 100;
		// 同比第二产业比重
		Double secondBasetoGOP = currentBase == 0 ? 0 : (secontBase / currentBase) * 100;
		// 同比第三产业比重
		Double thirdBasetoGOP = currentBase == 0 ? 0 : (thirdBase / currentBase) * 100;
		// 当期第一产业比重
		Double firstCurrent = getOceanRelatedEmployedContribution(indicatorAccountVO, FirstIndicatorName);
		// 当期第二产业比重
		Double secondCurrent = getOceanRelatedEmployedContribution(indicatorAccountVO, SecondIndicatorName);
		// 当期第三产业比重
		Double thirdCurrent = getOceanRelatedEmployedContribution(indicatorAccountVO, ThirdIndicatorName);

		Double multiplier = (firstBasetoGOP * firstCurrent) + (secondBasetoGOP * secondCurrent)
				+ (thirdBasetoGOP * thirdCurrent);
		Double divisor1 = Math.sqrt((firstBasetoGOP * firstBasetoGOP) + (secondBasetoGOP * secondBasetoGOP)
				+ (thirdBasetoGOP * thirdBasetoGOP));
		Double divisor2 = Math.sqrt((firstCurrent * firstCurrent) + (secondCurrent * secondCurrent)
				+ (thirdCurrent * thirdCurrent));

		Validate.isTrue(!(Double.valueOf(0).equals(divisor1 * divisor2)));

		Double result = (divisor1 * divisor2) == 0 ? 0 : multiplier / (divisor1 * divisor2);

		return Math.acos(result);

	}

	private Double geFirstIndicatorVal(IndicatorAccountVO indicatorAccountVO, int year, String name) {
		Double result = getInputOrAccountingIndicatorValue(indicatorAccountVO, year, name);
		if (result == null) {
			return 0d;
		} else {
			return result;
		}
	}

	private Double getBaseIndicatorVal(IndicatorAccountVO indicatorAccountVO, int year) {

		Double inputOrAccountingIndicatorValue = getInputOrAccountingIndicatorValue(indicatorAccountVO, year,
				BaseIndicatorName);
		Validate.isTrue(inputOrAccountingIndicatorValue != null);
		return inputOrAccountingIndicatorValue;
	}

	private Double getOceanRelatedEmployedContribution(IndicatorAccountVO indicatorAccountVO, String name) {
		Integer indicatorInputId = getIndicatorEvaluationId(name, indicatorAccountVO.getAreaId());
		// if (indicatorInputId == null) {
		// return Double.valueOf(0);
		// }

		Criteria cri = getIndicatorDataCri(indicatorAccountVO, indicatorAccountVO.getYear(), indicatorInputId);
		Double evaluationIndicatorValue = getEvaluationIndicatorValue(cri);
		if (evaluationIndicatorValue == null) {
			return 0d;
		} else {
			return evaluationIndicatorValue;
		}

	}

}
